![]() |
![]() |
|
Der Aufruf von Items liefert die Referenz auf das interne ObjectCollection-Objekt. Alle Elemente, die in der Listbox angezeigt werden, sind Mitglieder dieser Auflistung. Wenn wir der Listbox ein Element hinzufügen wollen, ein bestimmtes Element entfernen wollen oder nach einem bestimmten Element suchen, greifen wir auf die Methoden dieser Auflistung zurück. Hinzufügen von Listenelementen zur EntwicklungszeitManchmal ist es möglich, eine ListBox bereits zur Entwicklungszeit vollständig zu füllen. Sie brauchen in diesem Fall im Eigenschaftsfenster nur die Eigenschaft Items zu markieren und können über die Schaltfläche in der Wertespalte einen Dialog öffnen, in dem Sie die Listenelemente der Reihe nach eintragen.
Abbildung 16.16 Listenelemente im Eigenschaftsfenster eintragen Hinzufügen von ListenelementenMeistens werden Sie allerdings Listen erst zur Laufzeit dynamisch füllen können, um den unterschiedlichen Umgebungsbedingungen gerecht zu werden. Als Mitglieder einer Collection werden Listenelemente über Indizes verwaltet. Das erste Listenelement hat, wie üblich, den Index 0. Drei Methoden ermöglichen das Hinzufügen eines Elements in eine Listbox: Add, AddRange und Insert. Betrachten wir zuerst die Add-Methode, deren Rückgabewert der Index ist, an dem das Element hinzugefügt worden ist. Das hinzuzufügende Element wird dem Methodenaufruf als Argument übergeben. Dabei müssen wir feststellen, dass der Parameter nicht, wie eigentlich zu erwarten wäre, vom Typ string ist, sondern vom Typ object. Tatsächlich kann jede beliebige Referenz übergeben werden, angezeigt wird jedoch nur der Rückgabewert der Methode ToString. Im folgenden Codefragment werden mit der Add-Methode die drei Elemente Franz, Joseph und Uwe hinzugefügt. Das erste Element hat den Index 0, das zweite den Index 1, das dritte den Index 2.
Eine Alternative zum sich wiederholenden Add-Aufruf bietet die Methode AddRange, die ein Objekt-Array erwartet:
Soll ein neues Element nicht an das Ende angehängt werden, sondern eine bestimmte Position innerhalb aller Listenelemente einnehmen, hilft die Methode Insert weiter. Dem ersten Parameter wird der gewünschte Index des hinzuzufügenden Elements übergeben, dem zweiten Parameter das Element. Die folgende Anweisung fügt Peter mit dem Index 1 an der zweiten Position der Listbox ein:
Ist der Index größer ist als die Anzahl der Elemente in der Listbox, kommt es zu der Ausnahme ArgumentOutOfRangeException. Listenelemente können mit Sorted auch alphabetisch sortiert werden. Sorted ist standardmäßig auf false eingestellt. Fügen Sie ein Element in eine sortierte Liste ein, wird das neue Element direkt einsortiert. Steigern der Effizienz beim Hinzufügen von vielen ListenelementenDie Methode Add hat im Vergleich zur AddRange-Methode den Nachteil, dass die Listbox mit jedem hinzugefügten Listenelement neu aufgebaut wird. Handelt es sich um eine größere Elementanzahl, hat das einen spürbaren Leistungsverlust zur Folge. Besonders deutlich wird der Effekt, wenn die Listenelemente mit Sorted=true sortiert werden sollen. Die Listbox bietet uns Abhilfe: Mit der Methode BeginUpdate lässt sich das Aktualisieren einer Listbox so lange unterdrücken, bis EndUpdate aufgerufen wird. Der Leistungsgewinn kann unter Umständen drastisch sein. Die folgenden Anweisungen, die beispielsweise beim Klicken auf eine Schaltfläche ausgeführt werden, demonstrieren den Einsatz der beiden Methoden. Für die Dauer des Schleifendurchlaufs wird der Mauscursor als Sanduhr angezeigt, um zu signalisieren, dass die Anwendung eine länger andauernde Operation ausführt.
Den Effekt können Sie sehr gut beobachten, wenn Sie die Methodenaufrufe von BeginUpdate und EndUpdate auskommentieren. Der Aufbau der Listbox benötigt dann ein Vielfaches der Zeit. Das Löschen eines ElementsJedes Element in einer Listbox kann durch den in der Listbox angezeigten Text und durch seinen Index beschrieben werden. Das ListBox.ObjectCollection-Objekt berücksichtigt dies und stellt uns zwei Methoden zur Verfügung, um ein bestimmtes Element aus der Auflistung zu entfernen: Remove und RemoveAt. Remove erwartet als Argument die Referenz auf ein Objekt und wertet wiederum dessen ToString-Rückgabe aus, RemoveAt nimmt den Index entgegen. Wird ein Element mitten aus der Liste entfernt, verschieben sich alle Nachfolgeindizes, denn eine Auflistung kann niemals eine unbesetzte Position enthalten.
Sollen alle Listenelemente gleichzeitig gelöscht werden, hilft uns die Methode Clear weiter. Prüfen, ob ein Element in der Listbox enthalten istDie Listenelemente einer Listbox sind nicht eindeutig, d. h., dass Sie dasselbe Element auch mehrfach der Auflistung hinzufügen können. Um das zu vermeiden, muss ein hinzuzufügendes Element zuerst daraufhin überprüft werden, ob es bereits eingetragen ist. Die Information darüber liefert die Methode Contains unter Angabe des Objekts. Der Rückgabewert ist vom Typ bool und true, wenn das im Parameter genannte Objekt in der Liste enthalten ist.
Den Index eines bestimmten Elements abfragenWollen Sie von einem bestimmten Element in der Listbox den Index in der Auflistung erfahren, hilft die Methode IndexOf weiter.
Ist das angegebene Element in der Liste nicht enthalten, ist der Rückgabewert –1. Den Inhalt der Listbox kopierenMit der Methode CopyTo können Sie alle Listbox-Elemente in ein Array kopieren und diesem die Indexposition angeben, ab der die Elemente der Listbox in das Array hineinkopiert werden sollen. Im folgenden Codefragment wird die Methode dazu benutzt, um bestimmte Elemente der Auflistung in das Array names zu kopieren. Zur Initialisierung des Arrays wird mit der Eigenschaft Count des ListBox.ObjectCollection-Objekts die Anzahl der in der Listbox enthaltenen Elemente ermittelt, und dazu werden weitere 100 Elemente »zur Reserve« addiert. Der Inhalt von ListBox.ObjectCollection wird in das Array ab Index 20 kopiert.
16.11.2 Eigenschaften zur Darstellung einer Listbox
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void Form1_Load(object sender, EventArgs e) { |
| InstalledFontCollection myFonts = new InstalledFontCollection(); |
| FontFamily[] font = myFonts.Families; |
| for(int i = 0; i < font.Length; i++) |
| lstFonts.Items.Add(font[i].Name); |
| } |
Die Eigenschaft Families eines InstalledFontCollection-Objects liefert ein Array vom Typ FontFamily zurück. Dieser Typ definiert eine Schriftart und veröffentlicht die Eigenschaft Name, die den Bezeichner des Fonts liefert. In einer Schleife wird das Array vom ersten bis zum letzten Element durchlaufen und der Bezeichner der sich jeweils über dem Index im Zugriff befindlichen Schriftart mit der Add-Methode der Auflistung der Listbox hinzugefügt.

Hier klicken, um das Bild zu vergrößern
Abbildung 16.17 Anzeige aller installierten Fonts in einer Listbox
Wenn Sie möchten, können Sie die Listenelemente auch auf mehrere Spalten aufteilen. Die Verteilung der Spalten erfolgt dabei so, dass keine vertikalen Bildlaufleisten mehr notwendig sind, sondern nur noch eine horizontale, welche die Navigation zwischen den Spalten ermöglicht. Dazu muss die Eigenschaft MultiColumn=true gesetzt werden. Eine Listbox mit mehreren Spalten sehen Sie in Abbildung 16.18.

Hier klicken, um das Bild zu vergrößern
Abbildung 16.18 Mehrspaltige Anzeige in einer Listbox
Die Spaltenbreite können Sie mit ColumnWidth beeinflussen. Aber seien Sie hier vorsichtig. Wählen Sie nämlich eine zu geringe Breite, wird der »überhängende« Teil von der Folgespalte überdeckt. Der Standardwert von 0 legt eine vordefinierte Breite fest, die allerdings nicht die Lesbarkeit aller Elemente sicherstellt.
Belassen Sie es bei der Vorgabe, kann in einer Listbox zur Laufzeit nur ein Eintrag ausgewählt werden. Sie können aber auch festlegen, dass der Anwender gleichzeitig mehrere markieren kann. Dazu müssen Sie die Eigenschaft SelectionMode der Listbox entsprechend festlegen. Diese Eigenschaft bezieht ihre Werte aus der gleichnamigen Enumeration, die vier Mitglieder hat.
| Member | Beschreibung |
| None | Es kann kein Listenelement selektiert werden. |
| One | Es kann ein Listenelement selektiert werden. |
| MultiSimple | Es können mehrere Listenelemente ausgewählt werden. |
| MultiExtended | Es können mehrere Listenelemente ausgewählt werden. Dazu werden die Pfeiltasten, die (Strg)-Taste und die Umschalttaste benutzt. |
Bei der Einstellung MultiSimple kann der Anwender mittels Mausklick in beliebiger Reihenfolge die Elemente auswählen, die dann invertiert dargestellt werden. Zudem kann er mit den Pfeiltasten durch die Liste navigieren und mit der Leertaste das fokussierte Element selektieren. Ein Mausklick oder das Drücken der Leertaste auf ein ausgewähltes Element hebt die Markierung des Elements wieder auf.
Die Auswahl MultiExtended ist dann vorteilhaft, wenn der Anwender einen Bereich aufeinander folgender Elemente auswählen soll. Wird ein Element mit der Maus ausgewählt und danach die Umschalttaste gedrückt, sind nach dem Klick auf ein zweites Listenelement alle Elemente zwischen diesen beiden automatisch selektiert. Ähnlich kann auch die Auswahl mit der Tastatur erweitert werden, indem man die Umschalttaste beim Drücken der Pfeiltasten gedrückt hält.
Verwenden Sie eine Listbox, die nur die Auswahl eines Elements zulässt, gestaltet sich der Zugriff auf das entsprechende Element anders als bei einer Listbox mit Mehrfachauswahl. Betrachten wir zuerst Listboxen, deren Eigenschaft SelectionMode auf One eingestellt ist.
Am einfachsten ist es, die Eigenschaft Text der Listbox abzurufen, z.B.:
| MessageBox.Show(listBox1.Text); |
Nahezu gleichwertig können Sie auch über SelectedItem auf das ausgewählte Listenelement zugreifen, allerdings ist der Rückgabewert dieser Eigenschaft nicht vom Typ string, sondern die Referenz auf das Objekt. Dies macht unter Umständen eine Konvertierung mit ToString erforderlich, wenn die Zeichenfolge des Listeneintrags weiterverwendet werden soll.
| MessageBox.Show(listBox1.SelectedItem.ToString()); |
Eine dritte Möglichkeit bietet sich mit der Methode Items, welche die Referenz auf ListBox.ObjectCollection liefert. Die Auflistung stellt einen Indexer bereit, dem der Index des ausgewählten Elements übergeben wird. Weil der Indexer den Typ object ausgibt, muss die Rückgabe in eine Zeichenfolge umgewandelt werden:
| MessageBox.Show(listBox1.Items[12].ToString()); |
Die Indexangabe darf natürlich nicht statisch codiert werden, weil sie sich zur Laufzeit abhängig von der Wahl des Anwenders ändert. Hier hilft uns die Eigenschaft SelectedIndex der Listbox weiter, die den Index des ausgewählten Elements bereitstellt. Die Anweisung zur Auswertung der ausgewählten Elements über den Indexer der Auflistung muss daher lauten:
| MessageBox.Show(listBox1.Items[listBox1.SelectedIndex].ToString()); |
SelectedIndex ruft nicht nur den Index des ausgewählten Elements in einer Listbox ab, sondern kann ihn auch festlegen. Das ist für die Entwicklung sehr nützlich, denn standardmäßig wird nach dem Laden und Anzeigen eines Formulars kein Listenelement vorselektiert.
In einer Listbox führt sehr häufig das Anklicken eines Listenelements zur sofortigen Verarbeitung. Ein Click-Ereignis bietet das Listenfeld nicht an, stattdessen das Ereignis SelectedIndexChanged. Sehen wir uns das an einem Beispiel an, dessen Form zwei Listboxen enthält (siehe Abbildung 16.19).

Hier klicken, um das Bild zu vergrößern
Abbildung 16.19 Form des Beispiels »ChangeFont«
In der linken Listbox wird die Liste aller installierten Fonts angezeigt, in der rechten hat der Anwender die Auswahl der Schriftgröße. Die Änderung der Auswahl in einer der beiden Listboxen bewirkt in einer Textbox die Anpassung der Ausgabezeichenfolge.
| // -------------------------------------------------------------- |
| // Beispiel: ...\Kapitel 16\ChangeFont |
| // -------------------------------------------------------------- |
| private void Form1_Load(object sender, EventArgs e) { |
| InstalledFontCollection myFonts = new InstalledFontCollection(); |
| FontFamily[] fonts = myFonts.Families; |
| // Listbox mit einer Auswahl an Schriftgrößen füllen |
| for(int i = 8; i <= 24; i++) |
| lstHoehe.Items.Add(Convert.ToString(i)); |
| // Listbox mit den installierten Schriftarten füllen |
| for(int i = 0; i < fonts.Length; i++) { |
| // prüfen, ob der Font das Regular-Format unterstützt |
| if(fonts[i].IsStyleAvailable(FontStyle.Regular)) |
| lstFonts.Items.Add(fonts[i].Name); |
| } |
| // Vorauswahl in den Listboxen |
| lstFonts.SelectedIndex = 0; |
| lstHoehe.SelectedIndex = lstHoehe.Items.IndexOf("10"); |
| // Registrierung der Ereignishandler |
| this.lstFonts.SelectedIndexChanged += |
| new EventHandler(listBox_SelectedIndexChanged); |
| this.lstHoehe.SelectedIndexChanged += |
| new EventHandler(listBox_SelectedIndexChanged); |
| // Schriftart in der Textbox an die Vorauswahl anpassen |
| this.ChangeFont(null, null); |
| } |
| // Ereignishandler |
| private void listBox_SelectedIndexChanged (object sender, EventArgs e) { |
| txtTesttext.Font = new Font(lstFonts.Text, Convert.ToSingle(lstHoehe.Text)); |
| } |
Zuerst werden die beiden Listboxen im Load-Ereignishandler der Form gefüllt. Die Elemente, die in der Listbox lstFonts angeboten werden, beziehen wir aus der Auflistung InstalledFontCollection. Wenn Sie jedoch denselben Code zum Füllen der Listbox einsetzen, der weiter oben beschrieben worden ist, werden Sie beim Testen der Anwendung möglicherweise eine unerwartete Feststellung machen: Es kommt zu einem Laufzeitfehler, weil die Zuweisung des in der Listbox markierten Fonts an die Eigenschaft Font der Textbox scheitert. Das ist beispielsweise bei der Schrift Monotype Corsiva der Fall, weil diese Schriftart das Format Regular nicht unterstützt. Um die Exception zu vermeiden und in der Listbox nur anerkannte Schriftarten anzuzeigen, wird vor dem Eintrag in die Listbox der Font zuerst mit der Eigenschaft IsStyleAvailable untersucht:
| if(fonts[i].IsStyleAvailable(FontStyle.Regular)) |
| lstFonts.Items.Add(fonts[i].Name); |
Weil in einer Listbox nach dem Start der Anwendung zunächst kein Element vorselektiert ist, sollten wir das per Programmcode für beide Listboxen vorgeben:
| lstFonts.SelectedIndex = 0; |
und
| lstHoehe.SelectedIndex = lstHoehe.Items.IndexOf("10"); |
Die Ereignisse SelectedIndexChanged der beiden Listboxen sind mit dem gemeinsamen Handler listBox_SelectedIndexChanged verknüpft, der die Schrift in der Textbox an die Auswahl anpasst.
Beachten Sie bitte unbedingt, dass die Registrierung der beiden Ereignishandler erst erfolgt, nachdem SelectedIndex festgelegt ist. Registrieren Sie vorher, wird der Ereignishandler aufgerufen, und der erste Aufruf des Ereignishandlers verursacht einen Laufzeitfehler, weil in der zweiten Listbox noch kein Eintrag markiert ist und daher einen ungültigen Wert aufweist.
Im Ereignishandler müssen wir nur die Font-Klasse mit einem passenden Konstruktor instanziieren. Geeignet ist in unserem Fall der Konstruktor, der die Zeichenfolge der Schriftart und die Größe der Schrift erwartet. Das neue Font-Objekt wird der Eigenschaft Font des Textfeldes zugewiesen. Dabei müssen wir allerdings noch den Übergabewert an den zweiten Parameter in den erwarteten Typ float konvertieren:
| txtTesttext.Font = new Font(lstFonts.Text, Convert.ToSingle(lstHoehe.Text)); |
Die letzte Anweisung im Load-Ereignishandler ist der Aufruf der Methode listBox_SelectedIndexChanged. Damit stellen wir sicher, dass nach dem Starten die Schriftart in der Textbox der Voreinstellung in den Listboxen entspricht.
Wird ein neues ListBox-Steuerelement erzeugt, lässt dies nur die Auswahl eines Elements zu. Die Eigenschaft SelectionMode gestattet die einfache oder erweiterte Mehrfachauswahl. Listenelemente mit Mehrfachauswahl verwalten die ausgewählten Listenelemente in zwei eigenen Auflistungen:
| SelectedObjectCollection |
| SelectedIndexCollection. |
Der Zugriff auf die Auflistungen erfolgt über die Eigenschaften SelectedIndices und SelectedItems. Beide ähneln sich in ihrem Verhalten und enthalten die ausgewählten Elemente der Listbox, zu denen sie eine Beziehung entweder über die Referenz oder über den Index herstellen.
Angenommen, »Peter«, »Uwe« und »Willi« sind in dieser Reihenfolge Listenelemente in der Listbox. Sind »Uwe« und »Willi« ausgewählt, enthält die Auflistung SelectedObjectCollection im ihrem ersten, nullindizierten Element den Verweis auf »Uwe«, im zweiten mit 1 indizierten Element den Verweis auf »Willi«. Analog verhält sich die Auflistung SelectedIndexCollection. Sie speichert jedoch nicht die Verweise, sondern den Index aus der Listbox.
Beide Auflistungen weisen die bekannten Eigenschaften und Methoden üblicher Auflistungen auf, beispielsweise Count, Contains, IndexOf sowie einen Indexer, um auf ein bestimmtes Element zuzugreifen.
Sehen wir uns an einem Beispiel an, wie ein Listenelement mit Mehrfachauswahl im Programmcode behandelt wird. Eine Form enthält dazu zwei Listboxen, die beide eine Mehrfachauswahl mit SelectionMode=MultiSimple zulassen (siehe Abbildung 16.20). In der linken wird nach dem Start der Anwendung eine Namensliste angezeigt. Der Benutzer kann mehrere Einträge in der linken Listbox auswählen und durch Klicken auf den oberen Button die ausgewählten Einträge in die rechte Listbox verschieben. Die markierten und verschobenen Einträge müssen danach in der Ursprungslistbox gelöscht werden. Der umgekehrte Vorgang, das Verschieben aus der rechten in die linke Listbox, verläuft analog.

Hier klicken, um das Bild zu vergrößern
Abbildung 16.20 Ausgabefenster des Beispiels »MultiSelectListbox«
| // --------------------------------------------------------- |
| // Beispiel: ...\Kapitel 16\MultiSelectListbox |
| // --------------------------------------------------------- |
| private void Form1_Load(object sender, EventArgs e) { |
| lstLeft.Items.AddRange(new string[]{"Peter", "Uwe", |
| "Michael", "Reiner", "Brigitte", "Thea", "Jackie"}); |
| } |
| private void btnLeftToRight_Click(object sender, EventArgs e) { |
| string[] arr = new string[lstLeft.SelectedItems.Count]; |
| lstLeft.SelectedItems.CopyTo(arr,0); |
| lstRight.Items.AddRange(arr); |
| // ausgewählte Elemente in linker Listbox löschen |
| for(int i = lstLeft.SelectedItems.Count-1; i >= 0 ; i--) |
| lstLeft.Items.RemoveAt(lstLeft.SelectedIndices[i]); |
| } |
| private void btnRightToLeft_Click(object sender, EventArgs e) { |
| string[] arr = new string[lstRight.SelectedItems.Count]; |
| lstRight.SelectedItems.CopyTo(arr,0); |
| lstLeft.Items.AddRange(arr); |
| // ausgewählte Elemente in rechter Listbox löschen |
| for(int i = lstRight.SelectedItems.Count-1; i >= 0 ; i--) |
| lstRight.Items.RemoveAt(lstRight.SelectedIndices[i]); |
| } |
Im Ereignishandler des Load-Ereignisses der Form wird die linke Listbox gefüllt. Die Ereignishandler zu den Click-Ereignissen der Schaltflächen gleichen sich bis auf die Bezeichner, so dass wir uns an dieser Stelle nur mit einem auseinander setzen müssen. Betrachten wir daher nur das Verschieben aus der linken in die rechte Listbox.
Die rechte Listbox soll mit der AddRange-Methode gefüllt werden. AddRange verlangt als Übergabeargument ein Objekt-Array, das wir uns vorher besorgen müssen. Deshalb deklarieren wir zuerst ein Array und initialisieren dieses mit einer Kapazität, die es erlaubt, es mit den ausgewählten Listenelementen aus der AusgangsListbox füllen zu können. Die Array-Größe resultiert aus der Anzahl der ausgewählten Elemente, die uns die Count-Eigenschaft der SelectedObjectCollection liefert, deren Referenz wir über SelectedItems als Rückgabewert erhalten.
| string[] arr = new string[lstLeft.SelectedItems.Count]; |
Mit
| lstLeft.SelectedItems.CopyTo(arr, 0); |
kopieren wir den Inhalt der Auflistung SelectedObjectCollection in das zuvor deklarierte Array arr, beginnend bei Index 0. Dieses Array übergeben wir der AddRange-Methode.
Nun müssen wir die ausgewählten und bereits verschobenen Listenelemente in der Listbox auch löschen. Der Indexer von SelectedIndexCollection der linken Listbox liefert uns als Rückgabewert die Indizes der ausgewählten Elemente. Diesen Rückgabewert übergeben wir der Methode RemoveAt der Listbox, die in einer Schleife für jedes markierte Listenelement aufgerufen wird:
| for(int i = listBox1.SelectedItems.Count – 1; i >= 0 ; i--) |
| listBox1.Items.RemoveAt(listBox1.SelectedIndices[i]); |
Beachten Sie, die Schleife ausgehend vom höchsten Zählerwert (welcher der Anzahl der ausgewählten Elemente minus 1 entspricht) bis 0 zu durchlaufen. Damit wird sichergestellt, dass zuerst das markierte Element mit dem höchsten Index aus der Listbox gelöscht wird und erst zum Schluss das mit dem kleinsten Index. Sie vermeiden so Fehler, die sich aus der Verschiebung der Indizes ergeben, denn auch die Listbox lässt keine unbesetzten Indizes zu und verschiebt alle Nachfolgeelemente um eine Position, um eine entstandene Lücke zu schließen. Die Übergabe des Schleifenzählers an SelectedIndices setzt aber eine konstante Zuordnung voraus, um einen logischen Fehler zu vermeiden.
Wenden Sie die Methode Sort auf die Listenelemente einer Listbox an, werden die sichtbaren Einträge alphabetisch sortiert. Eine andere Alternative bietet sich nicht an, da die Methode keine entsprechenden Überladungen hat. Manchmal ist es jedoch erforderlich, eine andere Sortierreihenfolge festzulegen.
Angenommen, in einem ListBox-Objekt sollen Objekte vom Typ Person angezeigt werden.
| public class Person { |
| public string Zuname; |
| public string Vorname; |
| public int Alter; |
| public Person(string zuname, string vorname, int alter) { |
| this.Zuname = zuname; |
| this.Vorname = vorname; |
| this.Alter = alter; |
| } |
| public override string ToString() { |
| return this.Zuname + " / " + this.Vorname + " / " + this.Alter; |
| } |
| } |
In der Klasse sind drei Felder öffentlich deklariert. Außerdem ist die Methode ToString überschrieben, weil die Listbox bei der Übergabe von Referenzen immer den Rückgabewert von ToString anzeigt. Die Überschreibung stellt sicher, dass zuerst der Zuname, dann der Vorname und zum Schluss das Alter für jeden Eintrag angezeigt werden.
Wir können uns vorstellen, dass die Elemente in der Listbox nach einem der drei Felder sortiert werden sollen. Die Sorted-Eigenschaft der Listbox leistet das nicht. Wir müssen einen anderen Weg gehen. Dabei hilft uns die überladene Methode Sort der ArrayList weiter, die uns die Möglichkeit gibt, eine Vergleichsklassenreferenz vom Typ IComparer zu übergeben.
| public virtual void Sort(IComparer); // Methode der Klasse ArrayList |
Eine Vergleichsklasse bereitzustellen, ist kein großes Problem. Das haben Sie bereits in Abschnitt 7 gelernt. Eine Hürde ist vielmehr, dass die Methode Sort auf die Referenz einer ArrayList aufgerufen wird, wir jedoch eine Listbox benutzerdefiniert sortieren wollen. Auch über diese Schwierigkeit hilft uns die Klasse ArrayList hinweg: Sie veröffentlicht die statische Methode Adapter, der die Referenz auf ein IList-Objekt übergeben wird.
| public static ArrayList Adapter(IList); |
Der Zufall will es so, dass die von der Eigenschaft Items zurückgelieferte Referenz vom Typ ListBox.ObjectCollection genau diese Schnittstelle implementiert. Damit hätten wir alle notwendigen Informationen gesammelt, die uns in die Lage versetzen, eine benutzerdefinierte Sortierung der Listboxelemente anzubieten. Das folgende Beispielprogramm zeigt den Programmcode. Die Form enthält neben einer Listbox auch drei Schaltflächen. Je nachdem, welche Schaltfläche der Benutzer anklickt, wird die Ausgabe in der Listbox nach einem der drei Felder sortiert.

Hier klicken, um das Bild zu vergrößern
Abbildung 16.21 Ausgabe des Beispiels »UserDefinedSortedListbox«
| // -------------------------------------------------------------- |
| // Beispiel: ...\Kapitel 16\UserDefinedSortedListbox |
| // -------------------------------------------------------------- |
| // Vergleichsklassen |
| public class CompareZuname : IComparer { |
| public int Compare(object pers1, object pers2) { |
| return ((Person)pers1).Zuname.CompareTo(((Person)pers2).Zuname); |
| } |
| } |
| public class CompareVorname : IComparer { |
| public int Compare(object pers1, object pers2) { |
| return ((Person)pers1).Vorname.CompareTo(((Person)pers2).Vorname); |
| } |
| } |
| public class CompareAlter : IComparer { |
| public int Compare(object pers1, object pers2) { |
| return ((Person)pers1).Alter.CompareTo(((Person)pers2).Alter); |
| } |
| } |
| // die Form |
| public partial class Form1 : Form { |
| private ArrayList arrList; |
| public Form1() { |
| InitializeComponent(); |
| Person[] persArray = new Person[]{ |
| new Person("Müller","Peter", 30), |
| new Person("Fischer", "Helmut", 56), |
| new Person("Popalowski", "Fred", 22), |
| new Person("Heinrich", "Walter", 29), |
| new Person("Meier", "Uwe", 12)}; |
| // das Array der Listbox übergeben |
| listBox1.Items.AddRange(persArray); |
| arrList = ArrayList.Adapter(listBox1.Items); |
| arrList.Sort(new CompareZuname()); |
| } |
| // Ereignishandler der drei Schaltflächen |
| private void Sortieren(object sender, EventArgs e) { |
| if(sender == btnZuname) |
| arrList.Sort(new CompareZuname()); |
| else if(sender == btnVorname) |
| arrList.Sort(new CompareVorname()); |
| else if(sender == btnAlter) |
| arrList.Sort(new CompareAlter()); |
| } |
| } |
Mit der Add-Methode des Objekts ObjectCollection lassen sich Listenelemente festlegen. Die .NET-Listbox erlaubt aber noch eine andere Alternative, indem Sie der Eigenschaft DataSource ein Objekt zuweisen. Bedingung ist, dass das Objekt die Schnittstelle IList implementiert. Üblicherweise wird diese Eigenschaft dazu benutzt, um beispielsweise ein ADO.NET-Objekt vom Typ DataSet bekannt zu geben Wir werden uns ADO.NET an späterer Stelle in diesem Buch widmen. Die Vorgehensweise lässt sich aber auch am Beispiel eines ArrayList-Objekts demonstrieren.
Haben Sie der Eigenschaft DataSource der Listbox einen Objektverweis zugewiesen, müssen Sie der Listbox mitteilen, welche Daten sie anzeigen soll. Hierzu übergeben Sie der Eigenschaft DisplayMember eine Zeichenfolge, welche die Eigenschaft angibt, deren Wert als Listenelement angezeigt werden soll. Ein Listenelement kann mit einem bestimmten Wert verknüpft sein. Angenommen, die der Eigenschaft DataSource bekannt gegebene Datenquelle beschreibt verschiedene Wohnungen, deren Beschreibung der Eigenschaft DisplayMember genannt wird, so könnte der mit jedem Listenelement verknüpfte Wert die Miete sein. Übergeben Sie der Eigenschaft ValueMember den Namen der Eigenschaft, welche die Miete liefert. Ausgewertet wird der unter ValueMember eingetragene Wert mit der Eigenschaft SelectedValue.
Machen wir uns das an einem konkreten Beispiel deutlich.
| public class Wohnung { |
| private double wohnflaeche; |
| private float miete; |
| private int zimmeranzahl; |
| public Wohnung(double flaeche, float preis, int anzahl) { |
| wohnflaeche = flaeche; |
| miete = preis; |
| zimmeranzahl = anzahl; |
| } |
| public double Wohnflaeche { |
| get {return wohnflaeche;} |
| } |
| public float Miete { |
| get {return miete;} |
| } |
| public string Bezeichnung { |
| get {return zimmeranzahl.ToString() + "-Zimmer-Wohnung";} |
| } |
| } |
In einer Listbox sollen die Bezeichner der Wohnungen angezeigt werden, in zwei Textboxen sowohl der Mietpreis als auch die Wohnfläche des ausgewählten Listenelements. Über die Add-Methode dürfte die Lösung keine Probleme bereiten, wir wollen aber nun alternativ die drei Eigenschaften DataSource, DisplayMember und ValueMember im Einsatz sehen.

Hier klicken, um das Bild zu vergrößern
Abbildung 16.22 Anzeigeformular des Beispiels »DataSourcePropertyDemo«
| // --------------------------------------------------------- |
| // Beispiel: ...\Kapitel 16\DataSourcePropertyDemo |
| // --------------------------------------------------------- |
| public partial class Form1 : Form { |
| // ArrayList-Objekt |
| private ArrayList wohnungen = new ArrayList(); |
| private void Form1_Load(object sender, EventArgs e){ |
| wohnungen.Add(new Wohnung(25, 300, 1)); |
| wohnungen.Add(new Wohnung(54, 470, 2)); |
| wohnungen.Add(new Wohnung(87, 729, 4)); |
| wohnungen.Add(new Wohnung(60, 650, 2)); |
| wohnungen.Add(new Wohnung(75, 680, 3)); |
| listBox1.DataSource = wohnungen; |
| listBox1.DisplayMember = "Bezeichnung"; |
| listBox1.ValueMember = "Miete"; |
| listBox1.SelectedIndex = 1; |
| } |
| // Ereignishandler des Events SelectedIndexChanged |
| private void listBox1_SelectedIndexChanged(...) { |
| txtMiete.Text = listBox1.SelectedValue.ToString(); |
| txtFlaeche.Text = |
| ((Wohnung)listBox1.SelectedItem ).Wohnflaeche.ToString(); |
| } |
| } |
DataSource erwartet die Referenz auf ein IList-implementierendes Objekt. Hier ist es ein ArrayList-Objekt mit der Bezeichnung wohnungen, dem mehrere Wohnung-Objekte hinzugefügt werden. Anschließend wird das ArrayList-Objekt der DataSource-Eigenschaft übergeben. Im ListBox-Steuerelement sollen die Inhalte der Eigenschaft Bezeichnung angezeigt werden. Das erreichen wir mit der Zuweisung:
| listBox1.DisplayMember = "Bezeichnung"; |
Weil ein Wohnung-Objekt zwei weitere Eigenschaften hat, steht es uns frei, eine der beiden zu wählen und der Eigenschaft ValueMember zu übergeben. Die Entscheidung ist in diesem Beispiel auf Miete gefallen.
| listBox1.ValueMember = "Miete"; |
ValueMember eine Eigenschaft anzugeben ist optional.
Wählt der Anwender ein Listenelement aus, wird das Ereignis SelectedIndexChanged ausgelöst. In der Textbox txtMiete zeigen wir den Mietpreis des gewählten Listenelements an, indem wir die Eigenschaft SelectedValue auswerten, die uns den Wert der unter ValueMember genannten Eigenschaft liefert. Die Wohnfläche in der Textbox txtFlaeche kann nur durch Auswertung von SelectedItem mit anschließender Konvertierung in den Typ Wohnung erfolgen.
| Hinweis Beachten Sie bitte, dass eine Listbox nicht mit Sorted sortiert werden kann, wenn die Eigenschaft DataSource zum Füllen benutzt wird. |
| << zurück |
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.